﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using Microsoft.Windows.Controls;
using Cleverscape.UTorrentClient.WebClient;
using System.Collections;
using System.Windows.Controls.Primitives;
using System.Data;
using System.Windows.Threading;
using System.ComponentModel;
using System.Collections.ObjectModel;
using System.Threading;
using System.Runtime.InteropServices;
using Microsoft.Win32;
using System.IO;
using System.Windows.Forms;
using System.Drawing;

namespace FatController
{
    public partial class WindowMain : System.Windows.Window
    {
        private UTorrentWebClient uTorrent;
        private WindowState _priorWindowState;
        private NotifyIcon _notifyIcon;
        private string _uTorrentAddress;
        private string _uTorrentUserName;
        private string _uTorrentPassword;

        public WindowMain()
        {
            InitializeComponent();
            _notifyIcon = new NotifyIcon();
            _notifyIcon.Icon = FatController.Properties.Resources.TheFatController;
            _notifyIcon.Visible = true;
            _notifyIcon.DoubleClick += new EventHandler(Icon_DoubleClick);
            LoadSettings();
            if (_uTorrentAddress != null && _uTorrentAddress.Length > 0)
            {
                InitialiseUTorrent();
            }
            _priorWindowState = WindowState;
        }

        void uTorrent_TorrentsUpdated(object sender, EventArgs e)
        {
            int NumberDownloadingSuccesfully = 0;
            int NumberDownloadingTotal = 0;
            int NumberSeedingSuccessfully = 0;
            int NumberSeedingTotal = 0;
            long SpeedUpTotal = 0;
            long SpeedDownTotal = 0;
            foreach (Torrent CurrentTorrent in uTorrent.Torrents)
            {
                SpeedUpTotal += CurrentTorrent.SpeedUploadBytes;
                SpeedDownTotal += CurrentTorrent.SpeedDownloadBytes;
                if ((CurrentTorrent.Status & TorrentStatus.Started) == TorrentStatus.Started)
                {
                    if (CurrentTorrent.ProgressPercent < 1)
                    {
                        NumberDownloadingSuccesfully++;
                        NumberDownloadingTotal++;
                    }
                    else
                    {
                        NumberSeedingSuccessfully++;
                        NumberSeedingTotal++;
                    }
                }
                else if ((CurrentTorrent.Status & TorrentStatus.Queued) == TorrentStatus.Queued)
                {
                    if (CurrentTorrent.ProgressPercent < 1)
                    {
                        NumberDownloadingTotal++;
                    }
                    else
                    {
                        NumberSeedingTotal++;
                    }
                }
            }
            string NotifyIconText = String.Format("{1}({2}) Downloading, {3}({4}) Seeding\r\n{5} Down, {6} Up", _uTorrentAddress, NumberDownloadingSuccesfully, NumberDownloadingTotal, NumberSeedingSuccessfully, NumberSeedingTotal, Utilities.FormatFileSize(SpeedDownTotal, true, "B/s"), Utilities.FormatFileSize(SpeedUpTotal, true, "B/s"));
            if (NotifyIconText.Length > 63)
            {
                NotifyIconText = NotifyIconText.Substring(0,63);
            }
            _notifyIcon.Text = NotifyIconText;
        }

        void uTorrent_TorrentAdded(object sender, TorrentEventArgs e)
        {
            if (WindowState == WindowState.Minimized)
            {
                _notifyIcon.ShowBalloonTip(4000, "Torrent Added To uTorrent", String.Format("Torrent '{0}' was added to uTorrent.", e.Torrent.Name), ToolTipIcon.Info);
            }
        }

        void uTorrent_TorrentFinishedDownloading(object sender, TorrentEventArgs e)
        {
            if (WindowState == WindowState.Minimized)
            {
                _notifyIcon.ShowBalloonTip(4000, "Torrent Download Complete", String.Format("Torrent '{0}' finished downloading.", e.Torrent.Name), ToolTipIcon.Info);
            }
        }

        void Icon_DoubleClick(object sender, EventArgs e)
        {
            this.Show();
            if (WindowState == WindowState.Minimized)
            {
                WindowState = _priorWindowState;
            }
        }

        protected override void OnClosing(CancelEventArgs e)
        {
            _notifyIcon.Visible = false;
            base.OnClosing(e);
        }
        protected override void OnStateChanged(EventArgs e)
        {
            if (WindowState == WindowState.Minimized)
            {
                this.Hide();
            }
            else
            {
                _priorWindowState = WindowState;
            }
            base.OnStateChanged(e);
        }

        public void ProcessCommandLine(IEnumerable<string> CommandLine)
        {
            (new AddFilesDelegate(AddFiles)).BeginInvoke(CommandLine, null, null);
        }

        private void AddFileButton_Click(object sender, RoutedEventArgs e)
        {
            System.Windows.Forms.OpenFileDialog FileOpen = new System.Windows.Forms.OpenFileDialog();
            FileOpen.AutoUpgradeEnabled = true;
            FileOpen.CheckFileExists = true;
            FileOpen.CheckPathExists = true;
            FileOpen.DefaultExt = ".torrent";
            FileOpen.DereferenceLinks = true;
            FileOpen.Filter = "Torrent File (*.torrent)|*.torrent";
            FileOpen.Multiselect = true;
            FileOpen.Title = "Choose Torrent File(s)";
            FileOpen.ShowDialog();
            (new AddFilesDelegate(AddFiles)).BeginInvoke(FileOpen.FileNames, null, null);
        }

        private void AddAddressButton_Click(object sender, RoutedEventArgs e)
        {
            WindowTorrentAddress AskTorrentAddress = new WindowTorrentAddress();
            AskTorrentAddress.Owner = this;
            AskTorrentAddress.ShowDialog();
            if (AskTorrentAddress.DialogResult.HasValue && AskTorrentAddress.DialogResult.Value)
            {
                (new AddAddressDelegate(AddAddress)).BeginInvoke(AskTorrentAddress.TextBoxAddress.Text, null, null);
            }
        }

        private void RemoveButton_Click(object sender, RoutedEventArgs e)
        {
            List<Torrent> TorrentsToRemove = new List<Torrent>();
            foreach (Torrent SelectedTorrent in DataGridTorrents.SelectedItems)
            {
                TorrentsToRemove.Add(SelectedTorrent);
            }
            (new PerformTorrentActionDelegate(PerformTorrentAction)).BeginInvoke(TorrentAction.Remove, TorrentsToRemove, null, null);
        }

        private void PlayButton_Click(object sender, RoutedEventArgs e)
        {
            List<Torrent> TorrentsToStart = new List<Torrent>();
            foreach (Torrent SelectedTorrent in DataGridTorrents.SelectedItems)
            {
                TorrentsToStart.Add(SelectedTorrent);
            }
            (new PerformTorrentActionDelegate(PerformTorrentAction)).BeginInvoke(TorrentAction.Start, TorrentsToStart, null, null);
        }

        private void PauseButton_Click(object sender, RoutedEventArgs e)
        {
            List<Torrent> TorrentsToPause = new List<Torrent>();
            foreach (Torrent SelectedTorrent in DataGridTorrents.SelectedItems)
            {
                TorrentsToPause.Add(SelectedTorrent);
            }
            (new PerformTorrentActionDelegate(PerformTorrentAction)).BeginInvoke(TorrentAction.Pause, TorrentsToPause, null, null);
        }

        private void StopButton_Click(object sender, RoutedEventArgs e)
        {
            List<Torrent> TorrentsToStop = new List<Torrent>();
            foreach (Torrent SelectedTorrent in DataGridTorrents.SelectedItems)
            {
                TorrentsToStop.Add(SelectedTorrent);
            }
            (new PerformTorrentActionDelegate(PerformTorrentAction)).BeginInvoke(TorrentAction.Stop, TorrentsToStop, null, null);
        }

        private void SettingsButton_Click(object sender, RoutedEventArgs e)
        {
            WindowSettings Settings = new WindowSettings();
            Settings.Owner = this;
            Settings.TextBoxAddress.Text = _uTorrentAddress;
            Settings.TextBoxUserName.Text = _uTorrentUserName;
            Settings.PasswordBoxPassword.Password = _uTorrentPassword;
            Settings.ShowDialog();
            if (Settings.DialogResult.HasValue && Settings.DialogResult.Value)
            {
                _uTorrentAddress = Settings.TextBoxAddress.Text;
                _uTorrentUserName =Settings.TextBoxUserName.Text;
                _uTorrentPassword = Settings.PasswordBoxPassword.Password;
                SaveSettings();
            }
        }

        private void SaveSettings()
        {
            Properties.Settings.Default.uTorrentAddress = _uTorrentAddress;
            Properties.Settings.Default.uTorrentUserName = _uTorrentUserName;
            Properties.Settings.Default.uTorrentPassword = _uTorrentPassword;
            Properties.Settings.Default.Save();
            if (uTorrent == null)
            {
                InitialiseUTorrent();
            }
            else
            {
                uTorrent.SetConnectionDetails(_uTorrentAddress, _uTorrentUserName, _uTorrentPassword);
            }
        }

        private void LoadSettings()
        {
            _uTorrentAddress = Properties.Settings.Default.uTorrentAddress;
            _uTorrentUserName = Properties.Settings.Default.uTorrentUserName;
            _uTorrentPassword = Properties.Settings.Default.uTorrentPassword;
        }

        private void InitialiseUTorrent()
        {
            uTorrent = new UTorrentWebClient(_uTorrentAddress, _uTorrentUserName, _uTorrentPassword, true, WindowMainWindow.Dispatcher);
            this.DataContext = uTorrent.Torrents;
            uTorrent.TorrentFinishedDownloading += new TorrentEventHandler(uTorrent_TorrentFinishedDownloading);
            uTorrent.TorrentAdded += new TorrentEventHandler(uTorrent_TorrentAdded);
            uTorrent.TorrentsUpdated += new EventHandler(uTorrent_TorrentsUpdated);
        }

        private enum TorrentAction
        {
            Start,
            Pause,
            Stop,
            Remove,
            RemoveData
        }

        private void PerformTorrentAction(TorrentAction Action, IEnumerable<Torrent> Torrents)
        {
            bool AllTorrentsArePaused = true;
            if (Action == TorrentAction.Pause)
            {
                foreach (Torrent CurrentTorrent in Torrents)
                {
                    if ((CurrentTorrent.Status & TorrentStatus.Paused) != TorrentStatus.Paused)
                    {
                        AllTorrentsArePaused = false;
                    }
                }
            }

            foreach (Torrent CurrentTorrent in Torrents)
            {
                switch (Action)
                {
                    case TorrentAction.Start:
                        CurrentTorrent.Start();
                        break;
                    case TorrentAction.Pause:
                        if (AllTorrentsArePaused)
                        {
                            CurrentTorrent.UnPause();
                        }
                        else
                        {
                            CurrentTorrent.Pause();
                        }
                        break;
                    case TorrentAction.Stop:
                        CurrentTorrent.Stop();
                        break;
                    case TorrentAction.Remove:
                        CurrentTorrent.Remove();
                        break;
                    case TorrentAction.RemoveData:
                        CurrentTorrent.Remove(true);
                        break;
                    default:
                        break;
                }
            }
        }

        private delegate void PerformTorrentActionDelegate(TorrentAction Action, IEnumerable<Torrent> Torrents);

        private void AddFiles(IEnumerable<string> FilesToAdd)
        {
            foreach (string FileName in FilesToAdd)
            {
                if (File.Exists(FileName))
                {
                    uTorrent.AddTorrent(FileName);
                }
            }
        }

        private delegate void AddFilesDelegate(IEnumerable<string> FilesToAdd);

        private void AddAddress(string AddressToAdd)
        {
            uTorrent.AddTorrentFromUrl(AddressToAdd);
        }

        private delegate void AddAddressDelegate(string AddressToAdd);

    }
}
